package web

import (
	"context"
	"fmt"
	"github.com/gin-gonic/gin"
	"github.com/redis/go-redis/v9"
	"go-admin/server/internal/domain"
	"go-admin/server/internal/service"
	"go-admin/server/internal/web/form"
	"go-admin/server/utils"
	"go.opentelemetry.io/otel"
	"go.opentelemetry.io/otel/trace"
	"net/http"
	"time"
)

var span trace.Span

type MenuHander struct {
	svc    service.MenuService
	tracer trace.Tracer
	cmd    redis.Cmdable
}

func NewMenuHander(svc service.MenuService, client redis.Cmdable) *MenuHander {
	return &MenuHander{
		svc:    svc,
		tracer: otel.GetTracerProvider().Tracer("菜单管理"),
		cmd:    client,
	}
}

func (m *MenuHander) RegisterRoutes(server *gin.Engine) {

	g := server.Group("/menu")

	g.GET("/lst", m.menuLst)
	g.PUT("/add", m.menuAdd)
	g.PUT("/edit", m.menuEdit)
	g.DELETE("/del", m.menuDel)
	g.GET("/search", m.menuSearch)
	g.GET("/left/menu", m.LeftMenu)

}

// menuLst 菜单列表
func (m *MenuHander) menuLst(ctx *gin.Context) {
	spanCtx := context.WithValue(ctx.Request.Context(), "Enable", true)
	spanCtx, span = m.tracer.Start(spanCtx, "web层:菜单列表")
	defer span.End()
	data, err := m.svc.GetMenuData(spanCtx)
	if err != nil {
		return
	}
	RenderJSON(ctx, http.StatusOK, 200, "ok", data)
}

// menuAdd 添加菜单
func (m *MenuHander) menuAdd(ctx *gin.Context) {
	spanCtx := context.WithValue(ctx.Request.Context(), "Enable", true)
	spanCtx, span = m.tracer.Start(spanCtx, "web层:添加菜单")
	defer span.End()
	var addMenu form.MenuData
	err := ctx.Bind(&addMenu)
	if err != nil {
		return
	}
	err = utils.Verify(addMenu, utils.MenuVerify)
	if err != nil {
		RenderJSON(ctx, http.StatusOK, http.StatusNoContent, err.Error(), nil)
		return
	}
	err = m.svc.AddMenu(spanCtx, domain.Menu{
		Name:       addMenu.Name,
		ParentID:   addMenu.ParentId,
		Path:       addMenu.Path,
		Permission: addMenu.Permission,
		FrontRoute: addMenu.FrontRoute,
		SortOrder:  int32(addMenu.SortOrder),
		Title:      addMenu.Title,
	})
	if err != nil {
		RenderJSON(ctx, http.StatusOK, http.StatusNoContent, "添加失败", nil)
		return
	}
	RenderJSON(ctx, http.StatusOK, http.StatusOK, "添加成功！", nil)
	return
}

// menuEdit 编辑菜单
func (m *MenuHander) menuEdit(ctx *gin.Context) {
	spanCtx := context.WithValue(ctx.Request.Context(), "Enable", true)
	spanCtx, span = m.tracer.Start(spanCtx, "web层:编辑菜单")
	defer span.End()
	var editMenu form.MenuData
	err := ctx.Bind(&editMenu)
	if err != nil {
		return
	}
	err = utils.Verify(editMenu, utils.MenuVerify)
	if err != nil {
		RenderJSON(ctx, http.StatusOK, http.StatusNoContent, err.Error(), nil)
		return
	}
	err = utils.Verify(editMenu, utils.MenuIDVerify)
	if err != nil {
		RenderJSON(ctx, http.StatusOK, http.StatusNoContent, err.Error(), nil)
		return
	}
	err = m.svc.EditMenu(spanCtx, domain.Menu{
		MenuID:     editMenu.MenuID,
		Name:       editMenu.Name,
		ParentID:   editMenu.ParentId,
		Path:       editMenu.Path,
		Permission: editMenu.Permission,
		FrontRoute: editMenu.FrontRoute,
		SortOrder:  int32(editMenu.SortOrder),
		Title:      editMenu.Title,
	})
	if err != nil {
		RenderJSON(ctx, http.StatusOK, http.StatusNoContent, "修改失败", nil)
		return
	}
	RenderJSON(ctx, http.StatusOK, http.StatusOK, "修改成功！", nil)
	return
}

// menuDel 删除菜单
func (m *MenuHander) menuDel(ctx *gin.Context) {
	spanCtx := context.WithValue(ctx.Request.Context(), "Enable", true)
	spanCtx, span = m.tracer.Start(spanCtx, "web层:删除菜单")
	defer span.End()
	var delMenu form.GetByMenuId
	err := ctx.Bind(&delMenu)
	if err != nil {
		return
	}
	err = utils.Verify(delMenu, utils.MenuIDVerify)
	if err != nil {
		RenderJSON(ctx, http.StatusOK, http.StatusNoContent, err.Error(), nil)
		return
	}
	err = m.svc.DelMenu(spanCtx, domain.Menu{
		MenuID: delMenu.MenuID,
	})
	if err != nil {
		fmt.Println(err.Error())
		RenderJSON(ctx, http.StatusOK, http.StatusNoContent, "删除失败", nil)
		return
	}
	RenderJSON(ctx, http.StatusOK, http.StatusOK, "删除成功！", nil)
	return
}

// menuSearch 搜索菜单
func (m *MenuHander) menuSearch(ctx *gin.Context) {
	spanCtx := context.WithValue(ctx.Request.Context(), "Enable", true)
	spanCtx, span = m.tracer.Start(spanCtx, "web层:搜索菜单")
	defer span.End()
	var searchMenu form.GetByTitle
	err := ctx.BindQuery(&searchMenu)
	if err != nil {
		return
	}
	err = utils.Verify(searchMenu, utils.MenuTitleVerify)
	if err != nil {
		RenderJSON(ctx, http.StatusOK, http.StatusNoContent, err.Error(), nil)
		return
	}
	data, err := m.svc.SearchMenu(spanCtx, domain.Menu{
		Title: searchMenu.Title,
	})
	RenderJSON(ctx, http.StatusOK, 200, "ok", data)
}

// LeftMenu 左侧菜单数据
func (m *MenuHander) LeftMenu(ctx *gin.Context) {
	spanCtx := context.WithValue(ctx.Request.Context(), "Enable", true)
	spanCtx, span = m.tracer.Start(spanCtx, "web层:左侧菜单")
	defer span.End()
	m.cmd.Set(spanCtx, "web", "web", time.Millisecond*100)
	data, err := m.svc.GetLeftMenu(spanCtx)
	if err != nil {
		return
	}
	RenderJSON(ctx, http.StatusOK, 200, "ok", data)
}
